package com.opennews.openplatform.controller;

import com.opennews.openplatform.dto.account.group.SwitchAccountGroupDto;
import com.opennews.openplatform.dto.authentication.LoginDto;
import com.opennews.openplatform.dto.authentication.PasswordDto;
import com.opennews.openplatform.dto.authentication.RefreshTokenDto;
import com.opennews.openplatform.dto.authentication.RegisterDto;
import com.opennews.openplatform.myspringbootcore.common.constant.ServerCode;
import com.opennews.openplatform.myspringbootcore.common.constant.ServerError;
import com.opennews.openplatform.myspringbootcore.dto.ApiResponse;
import com.opennews.openplatform.myspringbootcore.security.MyClaims;
import com.opennews.openplatform.myspringbootcore.security.MyUserDetails;
import com.opennews.openplatform.myspringbootcore.util.SharedUtil;
import com.opennews.openplatform.myspringbootmvccore.helper.HttpRequestHepler;
import com.opennews.openplatform.myspringbootmvccore.helper.HttpResponseHelper;
import com.opennews.openplatform.myspringbootmvccore.security.RequestIdentityExtractor;
import com.opennews.openplatform.service.AccountGroupService;
import com.opennews.openplatform.service.AuthenticationService;
import com.opennews.openplatform.service.UserService;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Map;

@RequiredArgsConstructor
@RestController
@RequestMapping("/authentication")
public class AuthenticationController {
    private final AccountGroupService accountGroupService;
    private final AuthenticationService authenticationService;
    private final UserService userService;
    private final HttpServletRequest request;
    private final RequestIdentityExtractor requestIdentityExtractor;
    private final HttpRequestHepler httpRequestHelper;
    private final HttpResponseHelper httpResponseHelper;

    @GetMapping("/check-on-username")
    public ResponseEntity<ApiResponse<Map<String, Object>>> checkOnUsername(@RequestParam String username) {
        boolean result = userService.checkOnUsername(username);

        return httpResponseHelper.getSuccessResponse(Map.of(
                "usernameExists", result
        ));
    }

    @PostMapping("/register")
    public ResponseEntity<ApiResponse<Object>> register(@Valid @RequestBody RegisterDto data) {
        accountGroupService.register(
                data.getUsername(),
                data.getPassword(),
                data.getFullName()
        );

        return httpResponseHelper.getSuccessResponse();
    }

    @PostMapping("/unregister")
    public ResponseEntity<ApiResponse<Map<String, Object>>> unregister(@Valid @RequestBody PasswordDto data) {
        MyClaims claims = requestIdentityExtractor.getClaims();
        String userId = claims.id;
        String username = claims.username;

        if (userService.validatePassword(username, data.getPassword())) {
            accountGroupService.unregister(userId);

            return httpResponseHelper.getSuccessResponse(Map.of("error", ""));
        } else {
            return httpResponseHelper.getSuccessResponse(Map.of("error", ServerError.ERROR_USER_ACCOUNT_BAD_CREDENTIAL));
        }
    }

    @PostMapping("/login")
    public ResponseEntity<ApiResponse<MyUserDetails>> login(@Valid @RequestBody LoginDto data) {
        Map<String, Object> result = authenticationService.authenticateByCredential(data.getUsername(), data.getPassword(), httpRequestHelper.getRequstIpAdress(), data.getDeviceInfo(), data.getSystemInfo());

        if (SharedUtil.isNullOrEmpty((String) result.get("errorCode"))) {
            return httpResponseHelper.getSuccessResponse((MyUserDetails) result.get("myUserDetails"));
        } else {
            httpResponseHelper.sendErrorResponse(HttpStatus.UNAUTHORIZED.value(), ServerCode.UNAUTHORIZED, result.get("errorCode").toString(), request.getRequestURI().trim());

            return null;
        }
    }

    @PostMapping("/refresh-token")
    public ResponseEntity<ApiResponse<MyUserDetails>> refreshToken(@Valid @RequestBody RefreshTokenDto data) {
        Map<String, Object> result = authenticationService.refreshToken(data.getRefreshToken(), httpRequestHelper.getRequstIpAdress(), data.getDeviceInfo(), data.getSystemInfo());

        if (SharedUtil.isNullOrEmpty((String) result.get("errorCode"))) {
            return httpResponseHelper.getSuccessResponse((MyUserDetails) result.get("myUserDetails"));
        } else {
            httpResponseHelper.sendErrorResponse(HttpStatus.UNAUTHORIZED.value(), ServerCode.UNAUTHORIZED, result.get("errorCode").toString(), request.getRequestURI().trim());

            return null;
        }
    }

    @PostMapping("/switch-account-group")
    public ResponseEntity<ApiResponse<MyUserDetails>> switchAccountGroup(@Valid @RequestBody SwitchAccountGroupDto data) {
        MyClaims claims = requestIdentityExtractor.getClaims();

        MyUserDetails result = authenticationService.switchAccountGroup(data.getAccountGroupId(),
                claims.id,
                claims.username,
                httpRequestHelper.getRequstIpAdress(),
                data.getDeviceInfo(),
                data.getSystemInfo());

        return httpResponseHelper.getSuccessResponse(result);
    }
}
